package com.gs.netty.support.properties;

import com.gs.netty.core.factory.NettyThreadFactory;
import com.gs.netty.support.SslConfig;
import lombok.Data;
import org.springframework.core.io.ClassPathResource;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.security.KeyStore;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Data
public class BaseNettyConfig {

    /**
     * 是否使用Epoll
     */
    public boolean useEpollNativeSelector;
    /**
     * 是否启用事件分发
     */
    public boolean useEventDispatch;

    /**
     *  netty的 workerGroup 线程数
     */
    public int workerGroupThreads;

    /**
     * 任务对象大小
     */
    public int processorCacheInit;
    /**
     * 任务对象最大大小
     */
    public int processorCacheSize;

    /**
     * 注意：
     * 使用 webSocket 子协议 来作为认证授权
     */
    public String subProtocols ="authorization";

    /**
     * 请求分发线程数据
     */
    public ThreadPoolProperties threadPool = new ThreadPoolProperties();

    /**
     * ssl配置
     */
    public SslConfig ssl = new SslConfig();


    public boolean isOpenSsl(){
        return ssl.isOpenSsl();
    }

    public boolean isNeedClientAuth(){
        return ssl.isNeedClientAuth();
    }

    public boolean isUseClientMode(){
        return ssl.isUseClientMode();
    }


    /**
     * 创建线程
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public ThreadPoolExecutor createThreadPoolExecutor()  {
        try {
            RejectedExecutionHandler executionHandler = threadPool.getThreadUncaughtExceptionHandlerClass().newInstance();
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(threadPool.getCorePoolSize()
                    , threadPool.getMaxPoolSize()
                    , threadPool.getKeepAliveTime()
                    , TimeUnit.MILLISECONDS
                    , new LinkedBlockingQueue<>(threadPool.getQueueCapacity())
                    , new NettyThreadFactory(threadPool.getThreadNamePrefix())
                    , executionHandler
            );
            return threadPoolExecutor;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }


    @Data
    public class ThreadPoolProperties {

        /**
         * 核心线程数
         */
        public int corePoolSize;
        /**
         * 最大线程数
         */
        public int maxPoolSize;
        /**
         * 队列等待时间（单位是毫秒）
         */
        public int keepAliveTime;
        /**
         * 队列容量
         */
        public int queueCapacity;

        /**
         * 是否允许核心线程在空闲时被回收
         */
        public boolean allowCoreThreadTimeOut;
        /**
         * 线程优先级
         */
        public int threadPriority;
        /**
         * 线程名称前缀
         */
        public String threadNamePrefix;
        /**
         * 线程名称后缀
         */
        public String threadNameSuffix;
        /**
         * 线程拒绝策略class 全限类名
         */
        public Class<RejectedExecutionHandler> threadUncaughtExceptionHandlerClass;

        public int getCorePoolSize() {
            return corePoolSize;
        }

        public void setCorePoolSize(int corePoolSize) {
            this.corePoolSize = corePoolSize;
        }

        public int getMaxPoolSize() {
            return maxPoolSize;
        }

        public void setMaxPoolSize(int maxPoolSize) {
            this.maxPoolSize = maxPoolSize;
        }

        public int getKeepAliveTime() {
            return keepAliveTime;
        }

        public void setKeepAliveTime(int keepAliveTime) {
            this.keepAliveTime = keepAliveTime;
        }

        public int getQueueCapacity() {
            return queueCapacity;
        }

        public void setQueueCapacity(int queueCapacity) {
            this.queueCapacity = queueCapacity;
        }

        public boolean isAllowCoreThreadTimeOut() {
            return allowCoreThreadTimeOut;
        }

        public void setAllowCoreThreadTimeOut(boolean allowCoreThreadTimeOut) {
            this.allowCoreThreadTimeOut = allowCoreThreadTimeOut;
        }

        public int getThreadPriority() {
            return threadPriority;
        }

        public void setThreadPriority(int threadPriority) {
            this.threadPriority = threadPriority;
        }

        public String getThreadNamePrefix() {
            return threadNamePrefix;
        }

        public void setThreadNamePrefix(String threadNamePrefix) {
            this.threadNamePrefix = threadNamePrefix;
        }

        public String getThreadNameSuffix() {
            return threadNameSuffix;
        }

        public void setThreadNameSuffix(String threadNameSuffix) {
            this.threadNameSuffix = threadNameSuffix;
        }

        public Class<RejectedExecutionHandler> getThreadUncaughtExceptionHandlerClass() {
            return threadUncaughtExceptionHandlerClass;
        }

        public void setThreadUncaughtExceptionHandlerClass(Class<RejectedExecutionHandler> threadUncaughtExceptionHandlerClass) {
            this.threadUncaughtExceptionHandlerClass = threadUncaughtExceptionHandlerClass;
        }
    }

    public SSLContext createSSLContext(String type, String path, String sslPassword) throws Exception {
        ClassPathResource classPathResource = new ClassPathResource(path);
        char[] passArray = sslPassword.toCharArray();
        SSLContext sslContext = SSLContext.getInstance("TLS"); // 这里TLS或者SSLv3都可以
        KeyStore ks = KeyStore.getInstance(type);
        // 加载keytool 生成的文件
        ks.load(classPathResource.getInputStream(), passArray);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, passArray);
        sslContext.init(kmf.getKeyManagers(), null, null);
        return sslContext;
    }

    public SSLContext createSSLContext() throws Exception {
        if (isOpenSsl()) {
            // 创建
            ClassPathResource classPathResource = new ClassPathResource(ssl.getPath());
            char[] passArray = ssl.getPassword().toCharArray();
            SSLContext sslContext = SSLContext.getInstance("TLS"); // 这里TLS或者SSLv3都可以
            KeyStore ks = KeyStore.getInstance(ssl.getType());
            // 加载keytool 生成的文件
            ks.load(classPathResource.getInputStream(), passArray);
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, passArray);
            sslContext.init(kmf.getKeyManagers(), null, null);
            return sslContext;
        }

        return null;
    }
}
